package com.reliable.service.iplocation.serviceimpl;

import com.reliable.service.iplocation.ipdomain.IPInfo;
import com.reliable.service.iplocation.service.IPLocationService;
import org.apache.commons.lang3.StringUtils;
import org.lionsoul.ip2region.xdb.Searcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;

/**
 * IP地址归属地查询服务实现类
 *
 * @author tianlian
 */
@Service
public class IPLocationServiceImpl implements IPLocationService {
    private static final Logger log = LoggerFactory.getLogger(IPLocationServiceImpl.class);

    /**
     * xdb文件路径，默认从classpath加载
     */
    @Value("${ip2region.db.path:localFile/ip2region.xdb}")
    private String dbPath;

    /**
     * 是否使用内存模式，提高查询性能
     */
    @Value("${ip2region.use.memory:true}")
    private boolean useMemory;

    /**
     * 查询器对象
     */
    private Searcher searcher;

    /**
     * 内存缓冲区
     */
    private byte[] vectorIndex;

    /**
     * 初始化IP库
     */
    @PostConstruct
    public void init() {
        try {
            // 从classpath加载xdb文件
            ClassPathResource resource = new ClassPathResource(dbPath);

            // 创建临时文件
            Path tempFile = Files.createTempFile("ip2region", ".xdb");
            try (InputStream inputStream = resource.getInputStream()) {
                Files.copy(inputStream, tempFile, StandardCopyOption.REPLACE_EXISTING);
            }

            String dbFilePath = tempFile.toFile().getPath();

            if (useMemory) {
                try {
                    // 加载整个 xdb 到内存
                    byte[] cBuff = Searcher.loadContentFromFile(dbFilePath);
                    searcher = Searcher.newWithBuffer(cBuff);

                    // 加载向量索引到内存，加速查询
                    vectorIndex = Searcher.loadVectorIndexFromFile(dbFilePath);
                    log.info("IP2Region initialized in memory mode successfully");
                } catch (Exception e) {
                    log.warn("Failed to load vector index, fallback to normal mode: {}", e.getMessage());
                    // 如果向量索引加载失败，尝试使用普通模式
                    searcher = Searcher.newWithFileOnly(dbFilePath);
                }
            } else {
                // 使用文件模式初始化查询器
                searcher = Searcher.newWithFileOnly(dbFilePath);
                log.info("IP2Region initialized in file mode successfully");
            }
        } catch (Exception e) {
            log.error("Failed to initialize IP2Region: {}", e.getMessage(), e);
        }
    }

    /**
     * 销毁资源
     */
    @PreDestroy
    public void destroy() {
        if (searcher != null) {
            try {
                searcher.close();
                log.info("IP2Region searcher closed");
            } catch (IOException e) {
                log.error("Error closing IP2Region searcher: {}", e.getMessage(), e);
            }
        }
    }

    /**
     * 查询IP归属地信息
     *
     * @param ip IP地址
     * @return 归属地信息，格式：国家|区域|省份|城市|ISP
     */
    @Override
    public String search(String ip) {
        if (StringUtils.isEmpty(ip)) {
            return "未知";
        }

        try {
            return searcher.search(ip);
        } catch (Exception e) {
            log.error("Error searching IP location for {}: {}", ip, e.getMessage(), e);
            return "查询失败";
        }
    }

    /**
     * 解析IP归属地信息
     *
     * @param ip IP地址
     * @return 解析后的归属地和运营商信息
     */
    @Override
    public IPInfo parseIp(String ip) {
        String region = search(ip);
        IPInfo ipInfo = new IPInfo();

        if (StringUtils.isEmpty(region) || "查询失败".equals(region) || "未知".equals(region)) {
            ipInfo.setLocation("未知");
            ipInfo.setIsp("未知");
            return ipInfo;
        }


        ipInfo.setIp(ip);
        // 解析返回的地址信息，格式：国家|区域|省份|城市|ISP
        String[] parts = region.split("\\|");

        // 构建地址信息
        StringBuilder location = new StringBuilder();


        String isp = "未知";

        if (parts.length >= 1 && StringUtils.isNotEmpty(parts[0]) && !"0".equals(parts[0])) {
            location.append(parts[0]); // 国家
            ipInfo.setCountry(parts[0]);
        }

        if (parts.length >= 3 && StringUtils.isNotEmpty(parts[2]) && !"0".equals(parts[2])) {
            if (location.length() > 0) {
                location.append(" ");
            }
            location.append(parts[2]); // 省份
            ipInfo.setProvince(parts[2]);
        }

        if (parts.length >= 4 && StringUtils.isNotEmpty(parts[3]) && !"0".equals(parts[3])) {
            if (location.length() > 0) {
                location.append(" ");
            }
            location.append(parts[3]); // 城市
            ipInfo.setCity(parts[3]);
        }

        // 提取ISP信息
        if (parts.length >= 5 && StringUtils.isNotEmpty(parts[4]) && !"0".equals(parts[4])) {
            isp = parts[4];
            ipInfo.setIsp(isp);
        }

        String locationStr = location.length() > 0 ? location.toString() : "未知";
        ipInfo.setLocation(locationStr);
        return ipInfo;
    }

    /**
     * IP信息类
     */
}
